// 1. apply & call & bind
let name = 'world'
this.name = 'thisName'
let obj = {
    name:'Laurel'
}
function fn(name1,name2){
    // this.name = 'here'
    console.log(name1+' '+this.name+' '+name2)
}
// fn.apply(obj,['first','last']) // first Laurel last 
// fn.call(this,'1','2') // 1 thisName 2
let fn1 = fn.bind(obj,'bind1','band2')
fn1() // => bind1 Laurel band2



// 2. apply 源码
let apply = function (x) {
  x = x || {};//防止this为null
  x['fn'] = this;
  var list = arguments[1] || [];
  var args = '';//参数列表
  var type;
  for (var i = 0; i < list.length; i++) {
    if (typeof list[i] === 'string') {//参数是字符串，需要在两边加引号，因为在拼接参数的时候会被丢掉
      type = '"' + list[i] + '"';
    }
    else if (typeof list[i] === 'function') {//参数是函数的话，"反编译"出函数的代码
      type = list[i].toString();
    }
    else if (typeof list[i] === 'object') {
      if (/function Array()/.test(list[i]['constructor'])) {//参数是数组则在数组两边加上[,]
        type = "[" + list[i] + "]";
      } else {
        type = JSON.stringify(list[i])//对象的话，json化，然后执行的时候反json化
      }
    } else {
      type = list[i];//数字类型
    }
    args = args + type + ',';
  }
  args = args.slice(0, args.length - 1);//去掉最后的逗号
  var q = new Function('var x = arguments[0];x.fn(' + args + ')')//new Function的时候作用域是独立的，无法访问call里面的x，所以需要传进去
  q(x)
}
function parse_Array_Object(arg) {
  //可以npm install traverse-deep和结合js的map函数进行相应处理，主要是遍历arg的每一个元素，进行类型判断，然后返回相应的字符串
  //to do ..
}

function a(a) {
  console.log(null, arguments)
}
a.apply(null, [1, 2])